/*
 *  gstore 被当做全局变量使用 没有vuex功能大，但是使用方便，通过store调用，可以储存到localstorage
 *  之后尽量加些功能 比如set get时触发一些钩子函数
 *
 */


const gstore = {};
let lsName = 'v3ws_gstore'

/*
 * 数据模型
 * readonly 设置为true则第一次set后不可修改
 * withLocalStorage 是否本地缓存
 * expireTime 缓存时间 单位为秒
 */
function createOne(key, value, withLocalStorage, expireTime, readonly) {
  //
  let o = {
    key: key,
    value: value,
    withLocalStorage: withLocalStorage,
    expireTime: expireTime,
    createTime: +new Date,
    readonly: readonly
  }
  return o

}
/*
 * 同步数据到localStorage
 *
 */
function updateLocalStorage() {
  let lstore = {}
  for (let x in gstore) {
    let v = getO(x)
    if (v) {
      lstore[x] = v
    }
  }
  if (!calcLocalStorageLength()) {
    console.error('localStorage 已满5M')
    // 淘汰策略  暂时不做
    // 使用频率排序
    // 创建时间排序
    // 失效时间
  }
  localStorage.setItem(lsName, JSON.stringify(lstore))
}

function calcLocalStorageLength() {
  let str = localStorage.getItem(lsName)
  if (str) {
    let l = getLength(str)
    if (l / 1024 / 1024 >= 5) {
      return false
    }
    return true
  }

  return true
}

//获得输入框中字符长度
function getLength(val) {
  var str = new String(val);
  var bytesCount = 0;
  for (var i = 0, n = str.length; i < n; i++) {
    var c = str.charCodeAt(i);
    if ((c >= 0x0001 && c <= 0x007e) || (0xff60 <= c && c <= 0xff9f)) {
      bytesCount += 1;
    } else {
      bytesCount += 2;
    }
  }
  return bytesCount;
}

function init() {
  // 如果有localstorage取出

  let lstore = JSON.parse(localStorage.getItem(lsName) || '{}')

  Object.entries(lstore).forEach(v => {
    let key = v[0],
      value = v[1]
    gstore[key] = value
  })
}

// 获取数据模型
function getO(key) {
  let value = gstore[key]
  // store  
  if (isExpire(key)) {
    // 删除数据
    del(key)
    return false
  }
  return value
}

function get(key) {
  let value = gstore[key]
  // store  
  if (isExpire(key)) {
    // 删除数据
    del(key)
    return undefined
  }

  return value.value // 该值可能为false

}

function del(key) {
  // 要不要严格校验呢 不用！！ 该方法不直接对外放开 ！！  内部调用前必须isExpire判断
  let value = gstore[key]
  if (!value) return true
  delete gstore[key]
  if (value.withLocalStorage) updateLocalStorage()
  return true
}

function isExpire(key) {
  let value = gstore[key]
  if (!value) return true
  if (value.expireTime > 0 && ~~(((+new Date) - value.createTime) / 1000) > value.expireTime) {
    return true
  }
  return false
}

function set(key, value, opt) {

  if (!opt) opt = {}
  let withLocalStorage = opt.withLocalStorage || false,
    expireTime = opt.expireTime || -1,
    readonly = opt.readonly || false
  let ovalue = get(key)
  if (ovalue && typeof ovalue === 'object') {
    withLocalStorage = ovalue.withLocalStorage
    expireTime = parseInt(ovalue.expireTime)
    readonly = ovalue.readonly
    if (ovalue.readonly) return true
  }
  let newvalue = createOne(key, value, withLocalStorage, expireTime, readonly)
  gstore[key] = newvalue
  if (withLocalStorage) updateLocalStorage()
  return true


}



function store() {
  let len = arguments.length;

  if (len == 1) {
    if (arguments[0] == '..all') {
      return gstore
    }
    return get(arguments[0])
  } else if (len < 4) {
    if(arguments[0] == '..del') return del(arguments[1])
    return set(...arguments)
  }

  console.error('length of arguments error')
  return false;

}

store.init = init //导出方法挂载init属性进行初始化


export default store
